package com.fgsort;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.utils.Exclude;
import com.utils.Files;
import com.utils.PlcSrc;
import com.utils.PlcSymbols;

public class PanelSymbolCheck extends JPanel {

	public String sSymbolFile1, sSymbolFile2;  
	public String sExcelSymbolFile;
	public String sExXML = "c:/tmp/symbols/SymCheckExcl.xml"; 
	
	private static final long serialVersionUID = 1L;
	private final JLabel lblSymbolCheck= new JLabel("Symbol Check - PLC/RuPlan");
	private final JSeparator separator_2 = new JSeparator();
	private final JSeparator separator = new JSeparator();
	private final JTextField txtSymbolFile1 = new JTextField("d:/tmp/symbols/");
	private final JButton btnSelectSymbolFile1 = new JButton("PLC");
	private final JTextField txtSymbolFile2 = new JTextField("d:/tmp/symbols/");
	private final JButton btnSelectSymbolFile2 = new JButton("RuPlan");
	private final JTextField txtExcelSymbolFile = new JTextField("auto generate filename");
	private final JButton btnCheck = new JButton("Compare");
	private final JTextField txtStatus = new JTextField(10);
	private final JLabel lblConfig = new JLabel("Configuration");
	private final JTextField txtXmlExclusion = new JTextField("d:/tmp/symbols/symCheckExcl.xml");
	private final JButton btnXmlExclusion = new JButton("Exclusion");
	private final JCheckBox chckbxOpenExport = new JCheckBox("Open .xls export");
	private final JButton exitButton = new JButton("Exit");
	private final JTextField txtPlcSrc = new JTextField("d:/tmp/symbols/");
	private final JButton btnPlcSrc = new JButton("Source");
	private final JCheckBox chckbxPlcSrc = new JCheckBox("PLC Src file");
	
	private ProgressDialog progressDialog;



	
	public PanelSymbolCheck(JFrame parent, String sPanelTitle) {
		setBackground(SystemColor.inactiveCaption);
		
		progressDialog = new ProgressDialog(parent);
		
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0};
		gridBagLayout.columnWeights = new double[]{1.0, 1.0, 1.0, 1.0, 1.0};
		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
		gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0};
		setLayout(gridBagLayout);
		
		setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), sPanelTitle));
		
		GridBagConstraints gbc_separator = new GridBagConstraints();
		gbc_separator.insets = new Insets(0, 0, 5, 0);
		gbc_separator.fill = GridBagConstraints.BOTH;
		gbc_separator.gridwidth = 6;
		gbc_separator.gridx = 0;
		gbc_separator.gridy = 0;
		separator.setForeground(new Color(119, 136, 153));
		add(separator, gbc_separator);
		
		GridBagConstraints gbc_lblSymbolCheck = new GridBagConstraints();
		gbc_lblSymbolCheck.insets = new Insets(0, 0, 5, 0);
		gbc_lblSymbolCheck.gridwidth = 6;
		gbc_lblSymbolCheck.gridx = 0;
		gbc_lblSymbolCheck.gridy = 1;
		lblSymbolCheck.setForeground(Color.BLACK);
		lblSymbolCheck.setFont(new Font("Tahoma", Font.BOLD, 13));
		add(lblSymbolCheck, gbc_lblSymbolCheck);
		
		GridBagConstraints gbc_separator_2 = new GridBagConstraints();
		gbc_separator_2.insets = new Insets(0, 0, 5, 0);
		gbc_separator_2.fill = GridBagConstraints.BOTH;
		gbc_separator_2.gridwidth = 6;
		gbc_separator_2.gridx = 0;
		gbc_separator_2.gridy = 2;
		separator_2.setForeground(new Color(119, 136, 153));
		add(separator_2, gbc_separator_2);
		
		GridBagConstraints gbc_txtHwCfgFile = new GridBagConstraints();
		gbc_txtHwCfgFile.gridwidth = 5;
		gbc_txtHwCfgFile.insets = new Insets(0, 0, 5, 5);
		gbc_txtHwCfgFile.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtHwCfgFile.gridx = 0;
		gbc_txtHwCfgFile.gridy = 3;
		txtSymbolFile1.setBackground(new Color(255, 255, 240));
		txtSymbolFile1.setEditable(false);
		txtSymbolFile1.setColumns(10);
		add(txtSymbolFile1, gbc_txtHwCfgFile);
		
		GridBagConstraints gbc_btnSelectHwCfg = new GridBagConstraints();
		gbc_btnSelectHwCfg.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnSelectHwCfg.insets = new Insets(0, 0, 5, 0);
		gbc_btnSelectHwCfg.gridx = 5;
		gbc_btnSelectHwCfg.gridy = 3;
		btnSelectSymbolFile1.setToolTipText("select plc symbol file to compare");
		btnSelectSymbolFile1.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnSelectSymbolFile1, gbc_btnSelectHwCfg);
		
		GridBagConstraints gbc_txtSymbolFile2 = new GridBagConstraints();
		gbc_txtSymbolFile2.gridwidth = 5;
		gbc_txtSymbolFile2.insets = new Insets(0, 0, 5, 5);
		gbc_txtSymbolFile2.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtSymbolFile2.gridx = 0;
		gbc_txtSymbolFile2.gridy = 4;
		txtSymbolFile2.setBackground(new Color(255, 255, 240));
		txtSymbolFile2.setEditable(false);
		txtSymbolFile2.setColumns(10);
		add(txtSymbolFile2, gbc_txtSymbolFile2);
		
		GridBagConstraints gbc_btnSelectSymbolFile2 = new GridBagConstraints();
		gbc_btnSelectSymbolFile2.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnSelectSymbolFile2.insets = new Insets(0, 0, 5, 0);
		gbc_btnSelectSymbolFile2.gridx = 5;
		gbc_btnSelectSymbolFile2.gridy = 4;
		btnSelectSymbolFile2.setToolTipText("select ruplan symbol file to compare");
		btnSelectSymbolFile2.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnSelectSymbolFile2, gbc_btnSelectSymbolFile2);
		
		GridBagConstraints gbc_txtPlcSrc = new GridBagConstraints();
		gbc_txtPlcSrc.gridwidth = 5;
		gbc_txtPlcSrc.insets = new Insets(0, 0, 5, 5);
		gbc_txtPlcSrc.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtPlcSrc.gridx = 0;
		gbc_txtPlcSrc.gridy = 5;
		txtPlcSrc.setEnabled(false);
		txtPlcSrc.setToolTipText("Select the plc source file location");
		txtPlcSrc.setEditable(false);
		txtPlcSrc.setColumns(10);
		add(txtPlcSrc, gbc_txtPlcSrc);
		
		GridBagConstraints gbc_btnPlcSrc = new GridBagConstraints();
		gbc_btnPlcSrc.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnPlcSrc.insets = new Insets(0, 0, 5, 0);
		gbc_btnPlcSrc.gridx = 5;
		gbc_btnPlcSrc.gridy = 5;
		btnPlcSrc.setEnabled(false);
		btnPlcSrc.setToolTipText("Select the plc source file");
		btnPlcSrc.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnPlcSrc, gbc_btnPlcSrc);
		
		GridBagConstraints gbc_txtExcelFile = new GridBagConstraints();
		gbc_txtExcelFile.gridwidth = 5;
		gbc_txtExcelFile.insets = new Insets(0, 0, 5, 5);
		gbc_txtExcelFile.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtExcelFile.gridx = 0;
		gbc_txtExcelFile.gridy = 7;
		txtExcelSymbolFile.setBackground(new Color(250, 235, 215));
		txtExcelSymbolFile.setEditable(false);
		txtExcelSymbolFile.setColumns(10);
		add(txtExcelSymbolFile, gbc_txtExcelFile);
		
		GridBagConstraints gbc_btnCheck = new GridBagConstraints();
		gbc_btnCheck.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnCheck.insets = new Insets(0, 0, 5, 0);
		gbc_btnCheck.gridx = 5;
		gbc_btnCheck.gridy = 7;
		btnCheck.setToolTipText("compare plc->ruplan symbols and generate excel report");
		btnCheck.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnCheck, gbc_btnCheck);
		
		GridBagConstraints gbc_lblConfig = new GridBagConstraints();
		gbc_lblConfig.anchor = GridBagConstraints.WEST;
		gbc_lblConfig.gridwidth = 6;
		gbc_lblConfig.insets = new Insets(0, 0, 5, 0);
		gbc_lblConfig.gridx = 0;
		gbc_lblConfig.gridy = 9;
		lblConfig.setForeground(Color.DARK_GRAY);
		lblConfig.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblConfig, gbc_lblConfig);
		
		GridBagConstraints gbc_chckbxPlcSrc = new GridBagConstraints();
		gbc_chckbxPlcSrc.anchor = GridBagConstraints.WEST;
		gbc_chckbxPlcSrc.insets = new Insets(0, 0, 5, 5);
		gbc_chckbxPlcSrc.gridx = 0;
		gbc_chckbxPlcSrc.gridy = 10;
		chckbxPlcSrc.setBackground(SystemColor.inactiveCaption);
		add(chckbxPlcSrc, gbc_chckbxPlcSrc);
		
		GridBagConstraints gbc_chckbxOpenExport = new GridBagConstraints();
		gbc_chckbxOpenExport.anchor = GridBagConstraints.WEST;
		gbc_chckbxOpenExport.insets = new Insets(0, 0, 5, 5);
		gbc_chckbxOpenExport.gridx = 0;
		gbc_chckbxOpenExport.gridy = 11;
		chckbxOpenExport.setBackground(SystemColor.inactiveCaption);
		chckbxOpenExport.setSelected(true);
		add(chckbxOpenExport, gbc_chckbxOpenExport);
		
		GridBagConstraints gbc_txtXmlExclusion = new GridBagConstraints();
		gbc_txtXmlExclusion.gridwidth = 5;
		gbc_txtXmlExclusion.insets = new Insets(0, 0, 5, 5);
		gbc_txtXmlExclusion.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtXmlExclusion.gridx = 0;
		gbc_txtXmlExclusion.gridy = 13;
		txtXmlExclusion.setToolTipText("Select the FG .xml file location");
		txtXmlExclusion.setEditable(false);
		txtXmlExclusion.setColumns(10);
		add(txtXmlExclusion, gbc_txtXmlExclusion);
		
		GridBagConstraints gbc_btnXmlExclusion = new GridBagConstraints();
		gbc_btnXmlExclusion.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnXmlExclusion.insets = new Insets(0, 0, 5, 0);
		gbc_btnXmlExclusion.gridx = 5;
		gbc_btnXmlExclusion.gridy = 13;
		btnXmlExclusion.setToolTipText("Select plc exclusions .xml file");
		btnXmlExclusion.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnXmlExclusion, gbc_btnXmlExclusion);
		
		///button - select unsorted function group file
		btnXmlExclusion.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		sExXML = chooseFile("d:/tmp/symbols", "xml");
        		txtXmlExclusion.setText(sExXML);
        		}
        	}
        );
		
		GridBagConstraints gbc_btnPlcSource = new GridBagConstraints();
		gbc_btnPlcSource.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnPlcSource.gridwidth = 6;
		gbc_btnPlcSource.insets = new Insets(0, 0, 5, 0);
		gbc_btnPlcSource.gridx = 0;
		gbc_btnPlcSource.gridy = 14;
		
		exitButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				exitApp();
			}
		});
		exitButton.setFont(new Font("Tahoma", Font.BOLD, 13));
		add(exitButton, gbc_btnPlcSource);
		
		GridBagConstraints gbc_txtStatus = new GridBagConstraints();
		gbc_txtStatus.gridwidth = 6;
		gbc_txtStatus.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtStatus.gridx = 0;
		gbc_txtStatus.gridy = 15;
		txtStatus.setText("status");
		txtStatus.setEditable(false);
		add(txtStatus, gbc_txtStatus);

	
		///button - select file1
		btnSelectSymbolFile1.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		sSymbolFile1 = chooseFile(txtSymbolFile1.getText(), "asc");
        		txtSymbolFile1.setText(sSymbolFile1);
        		}
        	}
        );
		
		///button - select file2
		btnSelectSymbolFile2.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		sSymbolFile2 = chooseFile(txtSymbolFile2.getText(), "asc");
        		txtSymbolFile2.setText(sSymbolFile2);
        		}
        	}
        );
		
		///button - select plc source file
		btnPlcSrc.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				txtPlcSrc.setText(chooseFile(txtPlcSrc.getText(), "awl"));			
        		}
		});

		chckbxPlcSrc.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				if (chckbxPlcSrc.isSelected())	{
					btnPlcSrc.setEnabled(true);
					txtPlcSrc.setEnabled(true);
				}
				else	{
					btnPlcSrc.setEnabled(false);
					txtPlcSrc.setEnabled(false);
				}
			}	
			
		});

		///button - check symbols config
		btnCheck.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					checkSymbols();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (ParserConfigurationException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (SAXException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				catch (IndexOutOfBoundsException e2) {
					System.out.println("WTF");
				}
			}
		});
		
	}

	private String chooseFile(String sFileLocation, String sFilter) {

		 String sfileName = null;
		  
		  //JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
		  JFileChooser chooser = new JFileChooser(sFileLocation);
		  FileNameExtensionFilter filter = new FileNameExtensionFilter(sFilter.toUpperCase(), sFilter);
		  chooser.setFileFilter(filter);
	      int option = chooser.showOpenDialog(PanelSymbolCheck.this);
	      if(option == JFileChooser.APPROVE_OPTION) {
	    	  txtStatus.setText("You chose "+((chooser.getSelectedFile()!=null)? chooser.getSelectedFile().getAbsoluteFile():"nothing"));
	    	  sfileName = chooser.getSelectedFile().getAbsoluteFile().toString();
	      }
	      if(option == JFileChooser.CANCEL_OPTION) {
	    	  txtStatus.setText("You canceled.");
	    	  sfileName = sFileLocation;
	       }
		  return sfileName;
	}

	public static String stripExtension(final String s)
	{
	    return s != null && s.lastIndexOf(".") > 0 ? s.substring(0, s.lastIndexOf(".")) : s;
	}

	///create automatic filename for symbol comparison excel file output
    private String getFilename(String text) {
    		
    	DateFormat df = new SimpleDateFormat("yyMMdd_HHmmss");
    	java.util.Date today = Calendar.getInstance().getTime();        
    	String sDateTime = df.format(today);
    	
    	if (text != null) {
    		String sFilename;
    		if (text.lastIndexOf("_") > 0)	{
    			sFilename = text.substring(0, text.lastIndexOf("_"));
    		}
    		else	{
    			if (text.lastIndexOf(".") > 0)	{
    				sFilename = text.substring(0, text.lastIndexOf("."));
    			}
    			else {
    				sFilename = text;
    			}
    		}
    		return sFilename + "_SYMBOLS_" + sDateTime + ".xls";
    	}
    	return "InvalidFileName" + "_SYMBOLS_" + sDateTime + ".xls";
	}
	
	///check symbol files
	public void checkSymbols() throws IOException, ParserConfigurationException, SAXException, IndexOutOfBoundsException
	{

		txtExcelSymbolFile.setText(getFilename(txtSymbolFile1.getText()));
		sExcelSymbolFile = txtExcelSymbolFile.getText(); 
		
		progressDialog.setMaximum(100);
		progressDialog.setVisible(true);
	
		SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
			
			@Override
			protected void done() {

				progressDialog.setVisible(false);
				
			}

			@Override
			protected void process(List<Integer> progress) {
				
				int percentage = progress.get(progress.size() - 1);
				
				progressDialog.setValue(percentage);
				progressDialog.setString(Integer.toString(percentage) + "%");
				
			}

			@Override
			protected Void doInBackground() throws IndexOutOfBoundsException, ParserConfigurationException, SAXException, IOException {
				// TODO Auto-generated method stub

				txtSymbolFile1.setText(sSymbolFile1);
				txtSymbolFile2.setText(sSymbolFile2);
				txtExcelSymbolFile.setText(sExcelSymbolFile);

				///declare symbol file lists 
				List<String> lstSymbolPlc = new ArrayList<String>();
				List<String> lstSymbolRuplan = new ArrayList<String>();

				///declare file1 lists
				List<String> lstFile1SymName = new ArrayList<String>();
				List<String> lstFile1SymIONum = new ArrayList<String>();
				List<String> lstFile1SymType = new ArrayList<String>();
				List<String> lstFile1SymComment = new ArrayList<String>();
				///declare file2 lists
				List<String> lstFile2SymName = new ArrayList<String>();
				List<String> lstFile2SymIONum = new ArrayList<String>();
				List<String> lstFile2SymType = new ArrayList<String>();
				List<String> lstFile2SymComment = new ArrayList<String>();

				Files gsf = new Files();
				lstSymbolPlc = gsf.getSymbolFile(sSymbolFile1);
				lstSymbolRuplan = gsf.getSymbolFile(sSymbolFile2);				
				
				///excel object - read file 
				//ExcelReadSymbolFile erf = new ExcelReadSymbolFile();

				///get symbol file lists
				//lstSymbolPlc = erf.ReadSymbolFile(sSymbolFile1);
				//lstSymbolRuplan = erf.ReadSymbolFile(sSymbolFile2);

				String fileXmlSymCheckExcl = txtXmlExclusion.getText();
						
				///get xml exclusions
				Element eXmlExcl = Exclude.getXmlExclusions(fileXmlSymCheckExcl);

				///build file1 symbol lists
				int j = 0;
				for (int i = 0; i < lstSymbolPlc.size()/4; i++) {
					if (!isExclusion(eXmlExcl, lstSymbolPlc.get(j), lstSymbolPlc.get(j+1), lstSymbolPlc.get(j+2), lstSymbolPlc.get(j+3)))	{
						lstFile1SymName.add(lstSymbolPlc.get(j));
						lstFile1SymIONum.add(lstSymbolPlc.get(j+1));
						lstFile1SymType.add(lstSymbolPlc.get(j+2));
						lstFile1SymComment.add(lstSymbolPlc.get(j+3));

						///display progress update
						publish((int)(Math.round((((float)i)/((float)(lstSymbolPlc.size()/4)))*100)));
					}
					j+=4;
				}
				
				///build file2 symbol lists
				j = 0;
				for (int i = 0; i < lstSymbolRuplan.size()/4; i++) {
					lstFile2SymName.add(lstSymbolRuplan.get(j));
					lstFile2SymIONum.add(lstSymbolRuplan.get(j+1));
					lstFile2SymType.add(lstSymbolRuplan.get(j+2));
					lstFile2SymComment.add(lstSymbolRuplan.get(j+3));
					//fireOptionEvent(new OptionEvent(this, lstFile2SymComment.get(i)));
					publish((int)(Math.round((((float)i)/((float)(lstSymbolRuplan.size()/4)))*100)));
					j+=4;
				}

				///combine symbol lists
				///declare file1 lists for inputs
				List<String> lstSortedFile1SymName_I = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_I = new ArrayList<String>();
				List<String> lstSortedFile1SymType_I = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_I = new ArrayList<String>();
				///declare File2 lists for inputs
				List<String> lstSortedFile2SymName_I = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_I = new ArrayList<String>();
				List<String> lstSortedFile2SymType_I = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_I = new ArrayList<String>();		
				///declare file1 lists for input bytes
				List<String> lstSortedFile1SymName_IB = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_IB = new ArrayList<String>();
				List<String> lstSortedFile1SymType_IB = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_IB = new ArrayList<String>();
				///declare File2 lists for inputs bytes
				List<String> lstSortedFile2SymName_IB = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_IB = new ArrayList<String>();
				List<String> lstSortedFile2SymType_IB = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_IB = new ArrayList<String>();
				///declare file1 lists for input bytes
				List<String> lstSortedFile1SymName_IW = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_IW = new ArrayList<String>();
				List<String> lstSortedFile1SymType_IW = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_IW = new ArrayList<String>();
				///declare File2 lists for inputs bytes
				List<String> lstSortedFile2SymName_IW = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_IW = new ArrayList<String>();
				List<String> lstSortedFile2SymType_IW = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_IW = new ArrayList<String>();		
				///declare file1 lists for input bytes
				List<String> lstSortedFile1SymName_ID = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_ID = new ArrayList<String>();
				List<String> lstSortedFile1SymType_ID = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_ID = new ArrayList<String>();
				///declare File2 lists for inputs bytes
				List<String> lstSortedFile2SymName_ID = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_ID = new ArrayList<String>();
				List<String> lstSortedFile2SymType_ID = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_ID = new ArrayList<String>();		
				///declare file1 lists for outputs
				List<String> lstSortedFile1SymName_Q = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_Q = new ArrayList<String>();
				List<String> lstSortedFile1SymType_Q = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_Q = new ArrayList<String>();
				///declare File2 lists for outputs
				List<String> lstSortedFile2SymName_Q = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_Q = new ArrayList<String>();
				List<String> lstSortedFile2SymType_Q = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_Q = new ArrayList<String>();		
				///declare file1 lists for QB
				List<String> lstSortedFile1SymName_QB = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_QB = new ArrayList<String>();
				List<String> lstSortedFile1SymType_QB = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_QB = new ArrayList<String>();
				///declare File2 lists for QB
				List<String> lstSortedFile2SymName_QB = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_QB = new ArrayList<String>();
				List<String> lstSortedFile2SymType_QB = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_QB = new ArrayList<String>();		
				///declare file1 lists for QW
				List<String> lstSortedFile1SymName_QW = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_QW = new ArrayList<String>();
				List<String> lstSortedFile1SymType_QW = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_QW = new ArrayList<String>();
				///declare File2 lists for QW
				List<String> lstSortedFile2SymName_QW = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_QW = new ArrayList<String>();
				List<String> lstSortedFile2SymType_QW = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_QW = new ArrayList<String>();		
				///declare file1 lists for QD
				List<String> lstSortedFile1SymName_QD = new ArrayList<String>();
				List<String> lstSortedFile1SymIONum_QD = new ArrayList<String>();
				List<String> lstSortedFile1SymType_QD = new ArrayList<String>();
				List<String> lstSortedFile1SymComment_QD = new ArrayList<String>();
				///declare File2 lists for QD
				List<String> lstSortedFile2SymName_QD = new ArrayList<String>();
				List<String> lstSortedFile2SymIONum_QD = new ArrayList<String>();
				List<String> lstSortedFile2SymType_QD = new ArrayList<String>();
				List<String> lstSortedFile2SymComment_QD = new ArrayList<String>();		

				///Input populate list file 1
				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("I") && !lstFile1SymIONum.get(i).contains("IB") && !lstFile1SymIONum.get(i).contains("IW") && !lstFile1SymIONum.get(i).contains("ID"))	{
						lstSortedFile1SymName_I.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_I.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_I.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_I.add(lstFile1SymComment.get(i));
					}
				}

				///Input populate list file 2
				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("I") && !lstFile2SymIONum.get(i).contains("IB") && !lstFile2SymIONum.get(i).contains("IW") && !lstFile2SymIONum.get(i).contains("ID"))	{
						lstSortedFile2SymName_I.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_I.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_I.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_I.add(lstFile2SymComment.get(i));
					}
				}

				///IB populate list file 1
				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("IB") && !lstFile1SymIONum.get(i).contains("IW") && !lstFile1SymIONum.get(i).contains("ID"))	{
						lstSortedFile1SymName_IB.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_IB.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_IB.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_IB.add(lstFile1SymComment.get(i));
					}
				}

				///IB populate list file 2
				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("IB") && !lstFile2SymIONum.get(i).contains("IW") && !lstFile2SymIONum.get(i).contains("ID"))	{
						lstSortedFile2SymName_IB.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_IB.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_IB.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_IB.add(lstFile2SymComment.get(i));
					}
				}

				///IW populate list file 1
				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("IW") && !lstFile1SymIONum.get(i).contains("IB") && !lstFile1SymIONum.get(i).contains("ID"))	{
						lstSortedFile1SymName_IW.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_IW.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_IW.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_IW.add(lstFile1SymComment.get(i));
					}
				}

				///IW populate list file 2
				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("IW") && !lstFile2SymIONum.get(i).contains("IB") && !lstFile2SymIONum.get(i).contains("ID"))	{
						lstSortedFile2SymName_IW.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_IW.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_IW.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_IW.add(lstFile2SymComment.get(i));
					}
				}		

				///ID populate list file 1
				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("ID") && !lstFile1SymIONum.get(i).contains("IB") && !lstFile1SymIONum.get(i).contains("IW"))	{
						lstSortedFile1SymName_ID.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_ID.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_ID.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_ID.add(lstFile1SymComment.get(i));
					}
				}

				///ID populate list file 2
				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("ID") && !lstFile2SymIONum.get(i).contains("IB") && !lstFile2SymIONum.get(i).contains("IW"))	{
						lstSortedFile2SymName_ID.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_ID.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_ID.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_ID.add(lstFile2SymComment.get(i));
					}
				}	

				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("Q") && !lstFile1SymIONum.get(i).contains("QB") && !lstFile1SymIONum.get(i).contains("QW") && !lstFile1SymIONum.get(i).contains("QD"))	{
						lstSortedFile1SymName_Q.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_Q.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_Q.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_Q.add(lstFile1SymComment.get(i));
					}
				}

				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("Q") && !lstFile2SymIONum.get(i).contains("QB") && !lstFile2SymIONum.get(i).contains("QW") && !lstFile2SymIONum.get(i).contains("QD"))	{
						lstSortedFile2SymName_Q.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_Q.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_Q.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_Q.add(lstFile2SymComment.get(i));
					}
				}

				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("QB") && !lstFile1SymIONum.get(i).contains("QW") && !lstFile1SymIONum.get(i).contains("QD"))	{
						lstSortedFile1SymName_QB.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_QB.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_QB.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_QB.add(lstFile1SymComment.get(i));
					}
				}

				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("QB") && !lstFile2SymIONum.get(i).contains("QW") && !lstFile2SymIONum.get(i).contains("QD"))	{
						lstSortedFile2SymName_QB.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_QB.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_QB.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_QB.add(lstFile2SymComment.get(i));
					}
				}

				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("QW") && !lstFile1SymIONum.get(i).contains("QB") && !lstFile1SymIONum.get(i).contains("QD"))	{
						lstSortedFile1SymName_QW.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_QW.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_QW.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_QW.add(lstFile1SymComment.get(i));
					}
				}

				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("QW") && !lstFile2SymIONum.get(i).contains("QB") && !lstFile2SymIONum.get(i).contains("QD"))	{
						lstSortedFile2SymName_QW.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_QW.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_QW.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_QW.add(lstFile2SymComment.get(i));
					}
				}

				for (int i = 0; i < lstFile1SymIONum.size(); i++)	{
					if (lstFile1SymIONum.get(i).contains("QD") && !lstFile1SymIONum.get(i).contains("QB") && !lstFile1SymIONum.get(i).contains("QW"))	{
						lstSortedFile1SymName_QD.add(lstFile1SymName.get(i));
						lstSortedFile1SymIONum_QD.add(lstFile1SymIONum.get(i));
						lstSortedFile1SymType_QD.add(lstFile1SymType.get(i));
						lstSortedFile1SymComment_QD.add(lstFile1SymComment.get(i));
					}
				}

				for (int i = 0; i < lstFile2SymIONum.size(); i++)	{
					if (lstFile2SymIONum.get(i).contains("QD") && !lstFile2SymIONum.get(i).contains("QB") && !lstFile2SymIONum.get(i).contains("QW"))	{
						lstSortedFile2SymName_QD.add(lstFile2SymName.get(i));
						lstSortedFile2SymIONum_QD.add(lstFile2SymIONum.get(i));
						lstSortedFile2SymType_QD.add(lstFile2SymType.get(i));
						lstSortedFile2SymComment_QD.add(lstFile2SymComment.get(i));
					}
				}

				///declare compiled symbol lists
				List<String> lstSymbolsWrite = new ArrayList<String>();

				List<String> lstSymbolsTmp_I = new ArrayList<String>();
				List<String> lstSymbols_I = new ArrayList<String>();

				List<String> lstSymbolsTmp_IB = new ArrayList<String>();
				List<String> lstSymbols_IB = new ArrayList<String>();		

				List<String> lstSymbolsTmp_IW = new ArrayList<String>();
				List<String> lstSymbols_IW = new ArrayList<String>();		

				List<String> lstSymbolsTmp_ID = new ArrayList<String>();
				List<String> lstSymbols_ID = new ArrayList<String>();		

				List<String> lstSymbolsTmp_Q = new ArrayList<String>();
				List<String> lstSymbols_Q = new ArrayList<String>();

				List<String> lstSymbolsTmp_QB = new ArrayList<String>();
				List<String> lstSymbols_QB = new ArrayList<String>();

				List<String> lstSymbolsTmp_QW = new ArrayList<String>();
				List<String> lstSymbols_QW = new ArrayList<String>();

				List<String> lstSymbolsTmp_QD = new ArrayList<String>();
				List<String> lstSymbols_QD = new ArrayList<String>();


				///create complete input list table structure
				for (int i = 0; i < 9000*8*8; i++)	{
					lstSymbolsTmp_I.add("");	///populate list with blanks
				}

				///set list values to actual Inputs
				for (int i = 0; i < lstSortedFile1SymIONum_I.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_I.get(i));
					lstSymbolsTmp_I.set((nOffset*8)+0, lstSortedFile1SymName_I.get(i));	
					lstSymbolsTmp_I.set((nOffset*8)+1, lstSortedFile1SymIONum_I.get(i));
					lstSymbolsTmp_I.set((nOffset*8)+2, lstSortedFile1SymType_I.get(i));
					lstSymbolsTmp_I.set((nOffset*8)+3, lstSortedFile1SymComment_I.get(i));
				}
				
				for (int i = 0; i < lstSortedFile2SymIONum_I.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_I.get(i));
					lstSymbolsTmp_I.set((nOffset*8)+4, lstSortedFile2SymName_I.get(i));	
					lstSymbolsTmp_I.set((nOffset*8)+5, lstSortedFile2SymIONum_I.get(i));
					lstSymbolsTmp_I.set((nOffset*8)+6, lstSortedFile2SymType_I.get(i));
					lstSymbolsTmp_I.set((nOffset*8)+7, lstSortedFile2SymComment_I.get(i));
				}

				///remove spare rows Inputs
				for (int i = 0; i < lstSymbolsTmp_I.size()/8; i++)	{
					if (lstSymbolsTmp_I.get((i*8)+1) != "" || lstSymbolsTmp_I.get((i*8)+5) != "")	{
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+0));
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+1));
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+2));
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+3));
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+4));
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+5));
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+6));
						lstSymbols_I.add(lstSymbolsTmp_I.get((i*8)+7));
					}
				}

				///create complete IB list table structure
				for (int i = 0; i < 9000*8; i++)	{
					lstSymbolsTmp_IB.add("");	///populate list with blanks
				}

				///set list values to actual IB
				for (int i = 0; i < lstSortedFile1SymIONum_IB.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_IB.get(i));
					lstSymbolsTmp_IB.set(nOffset*8+0, lstSortedFile1SymName_IB.get(i));	
					lstSymbolsTmp_IB.set(nOffset*8+1, lstSortedFile1SymIONum_IB.get(i));
					lstSymbolsTmp_IB.set(nOffset*8+2, lstSortedFile1SymType_IB.get(i));
					lstSymbolsTmp_IB.set(nOffset*8+3, lstSortedFile1SymComment_IB.get(i));
				}

				for (int i = 0; i < lstSortedFile2SymIONum_IB.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_IB.get(i));
					lstSymbolsTmp_IB.set(nOffset*8+4, lstSortedFile2SymName_IB.get(i));	
					lstSymbolsTmp_IB.set(nOffset*8+5, lstSortedFile2SymIONum_IB.get(i));
					lstSymbolsTmp_IB.set(nOffset*8+6, lstSortedFile2SymType_IB.get(i));
					lstSymbolsTmp_IB.set(nOffset*8+7, lstSortedFile2SymComment_IB.get(i));
				}

				///remove spare rows IB
				for (int i = 0; i < lstSymbolsTmp_IB.size()/8; i++)	{
					if (lstSymbolsTmp_IB.get((i*8)+1) != "" || lstSymbolsTmp_IB.get((i*8)+5) != "")	{
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+0));
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+1));
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+2));
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+3));
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+4));
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+5));
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+6));
						lstSymbols_IB.add(lstSymbolsTmp_IB.get((i*8)+7));
					}
				}

				///create complete ID list table structure
				for (int i = 0; i < 15000*8; i++)	{
					lstSymbolsTmp_IW.add("");	///populate list with blanks
				}

				///set list values to actual IW
				for (int i = 0; i < lstSortedFile1SymIONum_IW.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_IW.get(i));
					lstSymbolsTmp_IW.set(nOffset*8+0, lstSortedFile1SymName_IW.get(i));	
					lstSymbolsTmp_IW.set(nOffset*8+1, lstSortedFile1SymIONum_IW.get(i));
					lstSymbolsTmp_IW.set(nOffset*8+2, lstSortedFile1SymType_IW.get(i));
					lstSymbolsTmp_IW.set(nOffset*8+3, lstSortedFile1SymComment_IW.get(i));
				}

				for (int i = 0; i < lstSortedFile2SymIONum_IW.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_IW.get(i));
					lstSymbolsTmp_IW.set(nOffset*8+4, lstSortedFile2SymName_IW.get(i));	
					lstSymbolsTmp_IW.set(nOffset*8+5, lstSortedFile2SymIONum_IW.get(i));
					lstSymbolsTmp_IW.set(nOffset*8+6, lstSortedFile2SymType_IW.get(i));
					lstSymbolsTmp_IW.set(nOffset*8+7, lstSortedFile2SymComment_IW.get(i));
				}

				///remove spare rows IW
				for (int i = 0; i < lstSymbolsTmp_IW.size()/8; i++)	{
					if (lstSymbolsTmp_IW.get((i*8)+1) != "" || lstSymbolsTmp_IW.get((i*8)+5) != "")	{
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+0));
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+1));
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+2));
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+3));
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+4));
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+5));
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+6));
						lstSymbols_IW.add(lstSymbolsTmp_IW.get((i*8)+7));
					}
				}

				///create complete ID list table structure
				for (int i = 0; i < 9000*8; i++)	{
					lstSymbolsTmp_ID.add("");	///populate list with blanks
				}

				///set list values to actual ID
				for (int i = 0; i < lstSortedFile1SymIONum_ID.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_ID.get(i));
					lstSymbolsTmp_ID.set(nOffset*8+0, lstSortedFile1SymName_ID.get(i));	
					lstSymbolsTmp_ID.set(nOffset*8+1, lstSortedFile1SymIONum_ID.get(i));
					lstSymbolsTmp_ID.set(nOffset*8+2, lstSortedFile1SymType_ID.get(i));
					lstSymbolsTmp_ID.set(nOffset*8+3, lstSortedFile1SymComment_ID.get(i));
				}

				for (int i = 0; i < lstSortedFile2SymIONum_ID.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_ID.get(i));
					lstSymbolsTmp_ID.set(nOffset*8+4, lstSortedFile2SymName_ID.get(i));	
					lstSymbolsTmp_ID.set(nOffset*8+5, lstSortedFile2SymIONum_ID.get(i));
					lstSymbolsTmp_ID.set(nOffset*8+6, lstSortedFile2SymType_ID.get(i));
					lstSymbolsTmp_ID.set(nOffset*8+7, lstSortedFile2SymComment_ID.get(i));
				}

				///remove spare rows ID
				for (int i = 0; i < lstSymbolsTmp_ID.size()/8; i++)	{
					if (lstSymbolsTmp_ID.get((i*8)+1) != "" || lstSymbolsTmp_ID.get((i*8)+5) != "")	{
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+0));
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+1));
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+2));
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+3));
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+4));
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+5));
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+6));
						lstSymbols_ID.add(lstSymbolsTmp_ID.get((i*8)+7));
					}
				}

				///create complete Outputs list table structure
				for (int i = 0; i < 9000*8*8; i++)	{
					lstSymbolsTmp_Q.add("");	///populate list with blanks
				}
				///set list values to actual Outputs
				for (int i = 0; i < lstSortedFile1SymIONum_Q.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_Q.get(i));
					lstSymbolsTmp_Q.set((nOffset*8)+0, lstSortedFile1SymName_Q.get(i));	
					lstSymbolsTmp_Q.set((nOffset*8)+1, lstSortedFile1SymIONum_Q.get(i));
					lstSymbolsTmp_Q.set((nOffset*8)+2, lstSortedFile1SymType_Q.get(i));
					lstSymbolsTmp_Q.set((nOffset*8)+3, lstSortedFile1SymComment_Q.get(i));
				}
				for (int i = 0; i < lstSortedFile2SymIONum_Q.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_Q.get(i));
					lstSymbolsTmp_Q.set((nOffset*8)+4, lstSortedFile2SymName_Q.get(i));	
					lstSymbolsTmp_Q.set((nOffset*8)+5, lstSortedFile2SymIONum_Q.get(i));
					lstSymbolsTmp_Q.set((nOffset*8)+6, lstSortedFile2SymType_Q.get(i));
					lstSymbolsTmp_Q.set((nOffset*8)+7, lstSortedFile2SymComment_Q.get(i));
				}

				///remove spare rows
				for (int i = 0; i < lstSymbolsTmp_Q.size()/8; i++)	{
					if (lstSymbolsTmp_Q.get((i*8)+1) != "" || lstSymbolsTmp_Q.get((i*8)+5) != "")	{
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+0));
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+1));
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+2));
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+3));
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+4));
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+5));
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+6));
						lstSymbols_Q.add(lstSymbolsTmp_Q.get((i*8)+7));
					}
				}

				///create complete QB list table structure
				for (int i = 0; i < 9000*8; i++)	{
					lstSymbolsTmp_QB.add("");	///populate list with blanks
				}

				///set list values to actual QB
				for (int i = 0; i < lstSortedFile1SymIONum_QB.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_QB.get(i));
					lstSymbolsTmp_QB.set(nOffset*8+0, lstSortedFile1SymName_QB.get(i));	
					lstSymbolsTmp_QB.set(nOffset*8+1, lstSortedFile1SymIONum_QB.get(i));
					lstSymbolsTmp_QB.set(nOffset*8+2, lstSortedFile1SymType_QB.get(i));
					lstSymbolsTmp_QB.set(nOffset*8+3, lstSortedFile1SymComment_QB.get(i));
				}

				for (int i = 0; i < lstSortedFile2SymIONum_QB.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_QB.get(i));
					lstSymbolsTmp_QB.set(nOffset*8+4, lstSortedFile2SymName_QB.get(i));	
					lstSymbolsTmp_QB.set(nOffset*8+5, lstSortedFile2SymIONum_QB.get(i));
					lstSymbolsTmp_QB.set(nOffset*8+6, lstSortedFile2SymType_QB.get(i));
					lstSymbolsTmp_QB.set(nOffset*8+7, lstSortedFile2SymComment_QB.get(i));
				}

				///remove spare rows QB
				for (int i = 0; i < lstSymbolsTmp_QB.size()/8; i++)	{
					if (lstSymbolsTmp_QB.get((i*8)+1) != "" || lstSymbolsTmp_QB.get((i*8)+5) != "")	{
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+0));
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+1));
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+2));
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+3));
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+4));
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+5));
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+6));
						lstSymbols_QB.add(lstSymbolsTmp_QB.get((i*8)+7));
					}
				}

				///create complete QW list table structure
				for (int i = 0; i < 9000*8; i++)	{
					lstSymbolsTmp_QW.add("");	///populate list with blanks
				}

				///set list values to actual QW
				for (int i = 0; i < lstSortedFile1SymIONum_QW.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_QW.get(i));
					lstSymbolsTmp_QW.set(nOffset*8+0, lstSortedFile1SymName_QW.get(i));	
					lstSymbolsTmp_QW.set(nOffset*8+1, lstSortedFile1SymIONum_QW.get(i));
					lstSymbolsTmp_QW.set(nOffset*8+2, lstSortedFile1SymType_QW.get(i));
					lstSymbolsTmp_QW.set(nOffset*8+3, lstSortedFile1SymComment_QW.get(i));
				}

				for (int i = 0; i < lstSortedFile2SymIONum_QW.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_QW.get(i));
					lstSymbolsTmp_QW.set(nOffset*8+4, lstSortedFile2SymName_QW.get(i));	
					lstSymbolsTmp_QW.set(nOffset*8+5, lstSortedFile2SymIONum_QW.get(i));
					lstSymbolsTmp_QW.set(nOffset*8+6, lstSortedFile2SymType_QW.get(i));
					lstSymbolsTmp_QW.set(nOffset*8+7, lstSortedFile2SymComment_QW.get(i));
				}

				///remove spare rows QW
				for (int i = 0; i < lstSymbolsTmp_QW.size()/8; i++)	{
					if (lstSymbolsTmp_QW.get((i*8)+1) != "" || lstSymbolsTmp_QW.get((i*8)+5) != "")	{
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+0));
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+1));
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+2));
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+3));
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+4));
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+5));
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+6));
						lstSymbols_QW.add(lstSymbolsTmp_QW.get((i*8)+7));
					}
				}

				///create complete QD list table structure
				for (int i = 0; i < 9000*8; i++)	{
					lstSymbolsTmp_QD.add("");	///populate list with blanks
				}

				///set list values to actual QD
				for (int i = 0; i < lstSortedFile1SymIONum_QD.size(); i++)	{
					int nOffset = getOffset(lstSortedFile1SymIONum_QD.get(i));
					lstSymbolsTmp_QD.set(nOffset*8+0, lstSortedFile1SymName_QD.get(i));	
					lstSymbolsTmp_QD.set(nOffset*8+1, lstSortedFile1SymIONum_QD.get(i));
					lstSymbolsTmp_QD.set(nOffset*8+2, lstSortedFile1SymType_QD.get(i));
					lstSymbolsTmp_QD.set(nOffset*8+3, lstSortedFile1SymComment_QD.get(i));
				}

				for (int i = 0; i < lstSortedFile2SymIONum_QD.size(); i++)	{
					int nOffset = getOffset(lstSortedFile2SymIONum_QD.get(i));
					lstSymbolsTmp_QD.set(nOffset*8+4, lstSortedFile2SymName_QD.get(i));	
					lstSymbolsTmp_QD.set(nOffset*8+5, lstSortedFile2SymIONum_QD.get(i));
					lstSymbolsTmp_QD.set(nOffset*8+6, lstSortedFile2SymType_QD.get(i));
					lstSymbolsTmp_QD.set(nOffset*8+7, lstSortedFile2SymComment_QD.get(i));
				}

				///remove spare rows QD
				for (int i = 0; i < lstSymbolsTmp_QD.size()/8; i++)	{
					if (lstSymbolsTmp_QD.get((i*8)+1) != "" || lstSymbolsTmp_QD.get((i*8)+5) != "")	{
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+0));
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+1));
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+2));
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+3));
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+4));
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+5));
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+6));
						lstSymbols_QD.add(lstSymbolsTmp_QD.get((i*8)+7));
					}
				}

				lstSymbolsWrite.addAll(lstSymbols_I);
				lstSymbolsWrite.addAll(lstSymbols_IB);
				lstSymbolsWrite.addAll(lstSymbols_IW);
				lstSymbolsWrite.addAll(lstSymbols_ID);
				lstSymbolsWrite.addAll(lstSymbols_Q);
				lstSymbolsWrite.addAll(lstSymbols_QB);
				lstSymbolsWrite.addAll(lstSymbols_QW);
				lstSymbolsWrite.addAll(lstSymbols_QD);

				publish(80);

				ArrayList<List<String>> lstTable = new  ArrayList<List<String>>();
				
				SymbolCompare sc = new SymbolCompare();

				///send list to SymbolCompare
				if (chckbxPlcSrc.isSelected())	{	
					///with plc source file
					lstTable = sc.processTable(lstSymbolsWrite, PlcSrc.getIO(PlcSrc.getPlcSrc(txtPlcSrc.getText())), eXmlExcl);
				}
				else	{
					///without plc source file
					lstTable = sc.processTable(lstSymbolsWrite);
				}
				
				///update progress status
				publish(100);
				
				///excel object - write file
				ExcelWriteSymbolFile2 ewsf = new ExcelWriteSymbolFile2();
				ewsf.ExcelWriteSymbols(lstTable, sExcelSymbolFile, chckbxOpenExport.isSelected());
				
				return null;
			}
			
		};
		
		///run multi-thread
		worker.execute();
	}
	

	///Debug output - Event Listener
    public void fireOptionEvent(OptionEvent event) {
        Object[] listeners = listenerList.getListenerList();
         
        for(int i=0; i < listeners.length; i += 2) {
            if(listeners[i] == OptionListener.class) {
                ((OptionListener)listeners[i+1]).detailEventOccurred(event);
            }
        }
    }
    
    public void addOptionListener(OptionListener listener) {
        listenerList.add(OptionListener.class, listener);
    }

	///Debug output - Event Listener
    public void fireProgressEvent(ProgressEvent event) {
        Object[] listeners = listenerList.getListenerList();
         
        for(int i=0; i < listeners.length; i += 2) {
            if(listeners[i] == ProgressListener.class) {
                ((ProgressListener)listeners[i+1]).progressEventOccurred(event);
            }
        }
    }
    
    public void addProgressListener(ProgressListener listener) {
        listenerList.add(ProgressListener.class, listener);
    }
    
       
	//fireOptionEvent(new OptionEvent(this,sSymName));
    
	public int getOffset(String sOffset) {
    	int nOffset = 0;
    	int nNum = 0;
    	int nRem = 0;
    	
    	String sOffset1 = sOffset.replaceAll("[a-zA-Z]", "");
    	String sOffset2 = sOffset1.replaceAll("\\s+", "");
    	
    	if (sOffset.contains("."))	{
    		nNum = Integer.parseInt(sOffset2.substring(0, sOffset2.lastIndexOf(".")));
    		nRem = Integer.parseInt(sOffset2.substring(sOffset2.lastIndexOf(".")+1, sOffset2.length()));
    	
    		nOffset = nNum * 8 + nRem;
    	}
    	else	{
    		nOffset = Integer.parseInt(sOffset2);
    	}
    	
    	return nOffset;
    }
    

    ///check if XML exclusion exists in plc symbol table 
    public boolean isExclusion(Element docEle, String sSymName, String sSymIONum, String sSymType, String sSymComment) throws SAXException {

    	///check for symbol exclusions
    	NodeList nlExclusionSymbol = docEle.getElementsByTagName("symbol");

    	if (nlExclusionSymbol != null && nlExclusionSymbol.getLength() > 0) {

    		String sName;
    		String sAddressType;
    		String sComment;

    		for (int i = 0; i < nlExclusionSymbol.getLength(); i++) {
    			Node node = nlExclusionSymbol.item(i);
    			if (node.getNodeType() == Node.ELEMENT_NODE) {
    				Element e = (Element) node;
    				NodeList nlName = e.getElementsByTagName("name");
    				NodeList nlAddress = e.getElementsByTagName("AddressType");
    				NodeList nlComment = e.getElementsByTagName("comment");
    				sName = nlName.item(0).getChildNodes().item(0).getNodeValue().trim();

    				if (nlName.getLength() > 0 && nlAddress.getLength() > 0 && nlComment.getLength() > 0)	{
    					sAddressType = nlAddress.item(0).getChildNodes().item(0).getNodeValue().trim();
    					sComment = nlComment.item(0).getChildNodes().item(0).getNodeValue().trim();
    					if (sSymName.toLowerCase().contains(sName.toLowerCase()) && getAddressType(sSymIONum).equals(sAddressType) && sSymComment.contains(sComment) )	{
    						return true;
    					}
    				}
    				else {

    					if (nlName.getLength() > 0 && nlAddress.getLength() > 0)	{
    						sAddressType = nlAddress.item(0).getChildNodes().item(0).getNodeValue().trim();
    						if (sSymName.toLowerCase().contains(sName.toLowerCase()) && getAddressType(sSymIONum).equals(sAddressType) )	{
    							return true;
    						}
    					}

    					else	{ 
    						if (sSymName.toLowerCase().contains(sName.toLowerCase()))	{
    							//fireOptionEvent(new OptionEvent(this,sSymName));
    							return true;
    						}
    					}
    				}
    			}
    		}
    	}
    	
    	///check for range exclusions
    	NodeList nlExclusionRange = docEle.getElementsByTagName("range");

    	if (nlExclusionRange != null && nlExclusionRange.getLength() > 0) {

        	String sAddressType;
        	Float fStart, fEnd;

    		for (int i = 0; i < nlExclusionRange.getLength(); i++) {
    			Node node = nlExclusionRange.item(i);
    			if (node.getNodeType() == Node.ELEMENT_NODE) {
    				Element e = (Element) node;
    				NodeList nlStart = e.getElementsByTagName("start");
    				NodeList nlEnd = e.getElementsByTagName("end");
    				NodeList nlAddress = e.getElementsByTagName("AddressType");
    				
    				if (nlStart.getLength() > 0 && nlEnd.getLength() > 0 && nlAddress.getLength() > 0)	{
    					
    					sAddressType = nlAddress.item(0).getChildNodes().item(0).getNodeValue().trim();
    					fStart = Float.parseFloat(nlStart.item(0).getChildNodes().item(0).getNodeValue().trim());
    					fEnd = Float.parseFloat(nlEnd.item(0).getChildNodes().item(0).getNodeValue().trim());
    					
    					if (PlcSymbols.getAddress(sSymIONum) >= fStart && PlcSymbols.getAddress(sSymIONum) <= fEnd && getAddressType(sSymIONum).equals(sAddressType) )	{
    						return true;
    					}
    				}
    			}
    		}
    	}
    	
    	
    	return false;
    }
    
    /// !! REMOVE now in PlcSymbols !!
    ///find type of address (I, Q, IB, QB)
	public String getAddressType(String sAddress)	{
    	
		char[] chars=sAddress.toCharArray();
		char[] aAddressType = new char[5];
		Character[] aAddress=new Character[chars.length];

		for (int i = 0; i < chars.length; i++) {
			aAddress[i]=chars[i];
		}
		short k = 0;
		for (int j = 0; j < aAddress.length; j++)	{
			if (Character.isLetter(aAddress[j]))	{
				aAddressType[k] = aAddress[j];
				k++;
			}
		}

		StringBuilder sb = new StringBuilder(aAddressType.length);
		for (Character c : aAddressType)
			sb.append(c.charValue());

		String str = sb.toString().trim();

		return str;
	}

	/// !! REMOVE now in PlcSymbols !!
    public float getAddress(String sAddress) {

    	float fNum = 0;

    	String sAddress1 = sAddress.replaceAll("[a-zA-Z]", "");
    	String sAddress2 = sAddress1.replaceAll("\\s+", "");
    	
  		fNum = Float.parseFloat(sAddress2);
    	
    	return fNum;
    }
	
  
    private void exitApp() {
		System.exit(0);
	}

	public void setProgress(int percent) {
		
		
	}
    
}
